package cn.cdzdjd.service.impl;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.json.JSONArray;
import org.json.JSONObject;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import cn.cdzdjd.constant.BrowserConstant;
import cn.cdzdjd.dao.DictMapper;
import cn.cdzdjd.entity.Dict;
import cn.cdzdjd.exception.ErrorCode;
import cn.cdzdjd.exception.RenException;
import cn.cdzdjd.service.KuaiShouVideoService;
import cn.cdzdjd.util.JsoupUtil;
import cn.cdzdjd.util.UrlUtil;
import cn.cdzdjd.util.VendorVideoUtil;
import cn.cdzdjd.vo.VideoInfoVO;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class KuaiShouVideoServiceImpl implements KuaiShouVideoService {
	@Resource
	private DictMapper dictMapper;
	private final String videoUrl = "https://www.kuaishou.com/graphql";
	private final String photoUrl = "https://v.m.chenzhongtech.com/rest/wd/photo/info";

	@Override
	public VideoInfoVO getVideoInfo(String locationUrl) {
		Response response = JsoupUtil.getFinalUrlResponse(locationUrl);
		URL url = response.url();
		try {
			if (url.getPath().contains("/fw/photo/")) {
				log.info("快手图文");
				// return getPhotoInfoByUniRest(response);
				return getPhoto(response);
			}
			if (url.getPath().contains("/short-video/")) {
				log.info("快手视频");
				String photoId = url.getPath().replace("/short-video/", "");
				return getVideo(photoId);
			}
		} catch (Exception e) {
			e.printStackTrace();
			try { 
				// 兜底方案
				log.info("快手兜底方案");
				return getVideoAndPhoto(locationUrl);
			} catch (IOException e1) {
				throw new RenException(ErrorCode.PARSE_ERROR);
			}
		}
		return null;
	}

	private VideoInfoVO getVideoAndPhoto(String locationUrl) throws IOException {
		Map<String, List<String>> videoInfoMap = VendorVideoUtil.getImageAndVideoUrl(locationUrl);
		List<String> posterList = new ArrayList<>();
		if (videoInfoMap.get("posterList") == null) {
			String posterUrl = "https://www.cdzdjd.cn/default.jpg";
			posterList.add(posterUrl);

		} else {
			posterList.addAll(videoInfoMap.get("posterList"));
		}
		return new VideoInfoVO(videoInfoMap.get("videoList"), posterList, "未找到文案,请自行编写", null);
	}

	/**
	 * 获取视频信息
	 * 
	 * @param photoId
	 * @return
	 * @throws Exception
	 */
	private VideoInfoVO getVideo(String photoId) throws Exception {
		JSONObject body = genVideoBody(photoId);
		Map<String, String> header = genVideoHeader();
		Response videoRes = Jsoup.connect(videoUrl).ignoreContentType(true).ignoreHttpErrors(true).method(Method.POST)
				.headers(header).requestBody(body.toString()).userAgent(BrowserConstant.USER_AGENT_PC)
				.header("Accept", BrowserConstant.ACCEPT).execute();
		String jsonStr = videoRes.body();
		JSONObject json = new JSONObject(jsonStr);
		if (json.has("result") && json.getInt("result") == 2) {
			throw new RenException("作品未找到");
		}
		if (json.has("data")) {
			JSONObject data = json.getJSONObject("data");
			if (data.has("result")) {
				if (data.getInt("result") == 400002) {
					log.error("出现了验证码");
					throw new RenException(ErrorCode.PARSE_ERROR);
				}
			}
			JSONObject visionVideoDetail = data.getJSONObject("visionVideoDetail");
			if (visionVideoDetail.getInt("status") == 1) {
				JSONObject photo = visionVideoDetail.getJSONObject("photo");
				String title = photo.getString("caption");
				String poster = photo.getString("coverUrl");
				String videoUrl = photo.getString("photoUrl");
				List<String> posterList = new ArrayList<>();
				posterList.add(poster);
				List<String> videoList = new ArrayList<>();
				videoList.add(videoUrl);
				return new VideoInfoVO(videoList, posterList, title, null);
			}
		}
		throw new RenException(ErrorCode.PARSE_ERROR);
	}

	private Map<String, String> genVideoHeader() {
		Map<String, String> header = new HashMap<String, String>();
		header.put("HOST", "www.kuaishou.com");
		header.put("User-Agent", BrowserConstant.USER_AGENT_PC);
		LambdaQueryWrapper<Dict> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Dict::getCode, "ksvideo").or().eq(Dict::getId, 1);
		Dict dict = dictMapper.selectOne(wrapper);
		header.put("Cookie", dict.getContent());
		header.put("Content-Type", "application/json");
		return header;

	}

	/**
	 * 生成视频body内容
	 * 
	 * @param locationUrl
	 * @return
	 */
	private JSONObject genVideoBody(String photoId) {
		JSONObject body = new JSONObject();
		body.put("operationName", "visionVideoDetail");
		JSONObject variables = new JSONObject();
		variables.put("photoId", photoId);
		variables.put("page", "detail");
		body.put("variables", variables);
		body.put("query",
				"query visionVideoDetail($photoId: String, $type: String, $page: String) { visionVideoDetail(photoId: $photoId, type: $type, page: $page) { status type author { id name following headerUrl } photo { id duration caption likeCount realLikeCount coverUrl photoUrl liked timestamp expTag llsid viewCount videoRatio stereoType musicBlocked riskTagContent riskTagUrl manifest { mediaType businessType version adaptationSet { id duration representation {  id  defaultSelect  backupUrl  codecs  url  height  width  avgBitrate  maxBitrate  m3u8Slice  qualityType  qualityLabel  frameRate  featureP2sp  hidden  disableAdaptive } } } manifestH265 photoH265Url coronaCropManifest coronaCropManifestH265 croppedPhotoH265Url croppedPhotoUrl videoResource } tags { type name } commentLimit { canAddComment } llsid danmakuSwitch } } ");

		return body;
	}

	/**
	 * 获取图文信息
	 * 
	 * @param photoId
	 * @return
	 * @throws Exception
	 */
	private VideoInfoVO getPhoto(Response response) throws Exception {
		Map<String, String> params = UrlUtil.convertUrlParamsToMap(response.url());
		JSONObject body = genPhotoBody(params);
		Map<String, String> header = genPhotoHeader(response.url().toString());
		Response photoRes = Jsoup.connect(photoUrl).ignoreContentType(true).ignoreHttpErrors(true).method(Method.POST)
				.referrer(response.url().toString()).headers(header).requestBody(body.toString())
				.userAgent(BrowserConstant.USER_AGENT_PC).header("Accept", BrowserConstant.ACCEPT).execute();
		String jsonStr = photoRes.body();
		JSONObject json = new JSONObject(jsonStr);
		int code = json.getInt("result");
		if (code == 1) {
			JSONObject atlas = json.getJSONObject("atlas");
			String cdn = atlas.getJSONArray("cdnList").getJSONObject(0).getString("cdn");
			List<String> posterList = new ArrayList<>();

			JSONArray list = atlas.getJSONArray("list");
			for (int i = 0; i < list.length(); i++) {
				String path = list.getString(i);
				String posterUrl = "https://" + cdn + path;
				posterList.add(posterUrl);
			}
			String title = json.getJSONObject("photo").getString("caption");
			return new VideoInfoVO(null, posterList, title, null);
		}
		if (code == 2) {
			log.error("未找到作品");
			throw new RenException("作品未找到");
		}
		if (code == 2001) {
			log.error("出现验证码");
			throw new RenException(ErrorCode.PARSE_ERROR);
		}
		if (code == 223) {
			throw new RenException("作品已被删除");
		}
		throw new RenException(ErrorCode.PARSE_ERROR);
	}

	/**
	 * 生成图文请求体
	 * 
	 * @param params
	 * @return
	 */
	private JSONObject genPhotoBody(Map<String, String> params) {
		JSONObject requestBody = new JSONObject();
		requestBody.put("env", "SHARE_VIEWER_ENV_TX_TRICK");
		requestBody.put("fid", params.get("fid"));
		requestBody.put("h5Domain", "v.m.chenzhongtech.com");
		requestBody.put("isLongVideo", false);
		requestBody.put("kpn", params.get("kpn"));
		requestBody.put("photoId", params.get("photoId"));
		requestBody.put("shareChannel", params.get("cc"));
		requestBody.put("shareId", params.get("shareId"));
		requestBody.put("shareMethod", params.get("shareMethod"));
		requestBody.put("shareObjectId", params.get("shareObjectId"));
		requestBody.put("shareResourceType", params.get("shareResourceType"));
		requestBody.put("shareToken", params.get("shareToken"));
		requestBody.put("subBiz", params.get("subBiz"));
		return requestBody;
	}

	/**
	 * 生成图文请求头
	 * 
	 * @return
	 */
	private Map<String, String> genPhotoHeader(String referer) {
		Map<String, String> header = new HashMap<String, String>();
		header.put("Referer", referer);
		header.put("Host", "v.m.chenzhongtech.com");
		header.put("User-Agent", BrowserConstant.USER_AGENT_PC);
		LambdaQueryWrapper<Dict> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Dict::getCode, "ksphoto").or().eq(Dict::getId, 2);
		Dict dict = dictMapper.selectOne(wrapper);
		header.put("Cookie", dict.getContent());
		header.put("Content-Type", "application/json");
		return header;

	}

//	private VideoInfoVO getPhotoInfoByUniRest(Response jsoupRes) {
//		HttpResponse<String> response = Unirest.post("https://v.m.chenzhongtech.com/rest/wd/photo/info")
//				.header("Cookie", "did=web_49649051c8c14cfd9162f1d99057cc6b; didv=1718123380000")
//				.header("Referer", jsoupRes.url().toString()).header("Content-Type", "application/json")
//				.header("Host", "v.m.chenzhongtech.com")
//				.contentType("application/json").cookie("did", "web_49649051c8c14cfd9162f1d99057cc6b")
//				.cookie("didv", "1718123380000")
//				.body(genPhotoBody(UrlUtil.convertUrlParamsToMap(jsoupRes.url())).toString()).asString();
//		String jsonStr = response.getBody();
//		JSONObject json = new JSONObject(jsonStr);
//		int code = json.getInt("result");
//		if (code == 1) {
//			JSONObject atlas = json.getJSONObject("atlas");
//			String cdn = json.getJSONArray("cdnList").getJSONObject(0).getString("cdn");
//			List<String> posterList = new ArrayList<>();
//
//			JSONArray list = atlas.getJSONArray("list");
//			for (int i = 0; i < list.length(); i++) {
//				String path = list.getString(i);
//				String posterUrl = "https://" + cdn + path;
//				posterList.add(posterUrl);
//			}
//			String title = json.getJSONObject("photo").getString("caption");
//			return new VideoInfoVO(null, posterList, title, null);
//		}
//		if (code == 2) {
//			log.error("未找到作品");
//			throw new RenException("作品未找到");
//		}
//		if (code == 2001) {
//			log.error("出现验证码");
//			throw new RenException(ErrorCode.PARSE_ERROR);
//		}
//		return null;
//	}
}
